import React, {useCallback, useEffect, useRef, useState} from "react";
import ChatView from "@/components/Chat/ChatView.jsx";
import VoiceView from "@/components/Chat/VoiceView.jsx";
import MessageInput from "@/components/Chat/MessageInput.jsx";
import ChatInfoPanel from "@/components/Chat/ChatInfoPanel.jsx";
import {useLocation, useNavigate} from "react-router-dom";
import {Flex, Layout} from "antd";
import SpeechRecognition, {useSpeechRecognition,} from "react-speech-recognition";
import {createChat, updateChat} from "@/apis/chat.js";
import {analyzeGrammar, analyzePronunciation, saveAnalysis,} from "@/apis/analyzer.js";
import "./Common.css";
import {AppHeader} from "@/components/common/AppHeader.jsx";

const {Content} = Layout;

/**
 * 口语对话主页面
 */
export function ChatPage() {
  const location = useLocation();
  const {userId, chatInfo} = location.state || {};
  const [chatId, setChatId] = useState(null);
  const [viewMode, setViewMode] = useState("chat"); // "chat" 或 "voice"
  const [messages, setMessages] = useState([]);
  const navigate = useNavigate();

  // 转录
  const [recordingState, setRecordingState] = useState("idle"); // "idle"、"recording"、"stop"
  const {transcript, resetTranscript, browserSupportsSpeechRecognition} =
    useSpeechRecognition();

  // 录音（状态使用recordingState）
  const mediaRecorderRef = useRef(null);
  const audioChunksRef = useRef([]);
  const audioBlobRef = useRef(null);

  // 音频播放
  const audioPlayingRef = useRef(null);
  const audioQueueRef = useRef([]);

  // 切换页面模式
  const handleSwitch = () => {
    setViewMode((prev) => (prev === "chat" ? "voice" : "chat"));
    setRecordingState("idle");
    resetTranscript();
    setPaused(false); // 切换时恢复语音识别
    setNoSpeechCount(0);
  };

  // 创建聊天
  useEffect(() => {
    async function fetchChatId() {
      const chatId = await createChat(
        userId,
        chatInfo.mode,
        chatInfo.situation,
      );
      setChatId(chatId);
      console.log("chatId: ", chatId);
    }

    void fetchChatId();
  }, [userId, chatInfo.mode, chatInfo.situation]);

  function onClose() {
    // 关闭当前聊天，返回到主页面
    navigate("/");
  }

  function onSummarize() {
    // 跳转至总结页面
    navigate("/summary", {state: {chatId}});
  }

  // 播放音频
  const playAudio = useCallback((pcmBase64) => {
    const sampleRate = 24000;
    const numChannels = 1;

    // Base64 解码
    const binary = atob(pcmBase64);
    const pcmData = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
      pcmData[i] = binary.charCodeAt(i);
    }

    // 转为 16 位有符号整型 PCM
    const pcm16 = new Int16Array(pcmData.buffer);

    // 转为浮点数 [-1.0, 1.0]
    const float32 = new Float32Array(pcm16.length);
    for (let i = 0; i < pcm16.length; i++) {
      float32[i] = pcm16[i] / 32768;
    }

    // 创建音频上下文和播放器
    const audioCtx = new window.AudioContext();
    const audioBuffer = audioCtx.createBuffer(
      numChannels,
      float32.length,
      sampleRate,
    );
    audioBuffer.getChannelData(0).set(float32);

    const source = audioCtx.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(audioCtx.destination);
    source.start();

    // 设置播放结束回调
    source.onended = () => {
      audioPlayingRef.current = false;
      if (audioQueueRef.current.length > 0) {
        const next = audioQueueRef.current.shift();
        playAudio(next);
      }
    };
  }, []);
  // Chat模式
  const onStart = useCallback(
    async function () {
      // 开始录音与转录
      setRecordingState("recording");
      try {
        // 1. 开始录音
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: true,
        });
        const mediaRecorder = new MediaRecorder(stream, {
          mimeType: "audio/webm; codecs=opus",
        });
        mediaRecorderRef.current = mediaRecorder;
        audioChunksRef.current = [];
        mediaRecorder.ondataavailable = (event) => {
          if (event.data.size > 0) {
            audioChunksRef.current.push(event.data);
          }
        };
        mediaRecorder.start();
        // 2. 开始转录
        if (!browserSupportsSpeechRecognition) {
          console.error("浏览器不支持语音识别");
        }
        await SpeechRecognition.startListening({
          continuous: true,
          language: "en-US",
        });
      } catch (e) {
        setRecordingState("idle");
        console.error("开始录音与转录失败！", e);
      }
    },
    [browserSupportsSpeechRecognition],
  );

  const onStop = useCallback(async () => {
    // 停止录音与转录
    setRecordingState("stop");
    try {
      // 1. 停止转录
      await SpeechRecognition.stopListening();
      // 2. 停止录音
      if (mediaRecorderRef.current) {
        mediaRecorderRef.current.stop();
        mediaRecorderRef.current.onstop = () => {
          audioBlobRef.current = new Blob(audioChunksRef.current, {
            type: "audio/webm; codecs=opus",
          });
          audioChunksRef.current = [];
        };
      }
    } catch (e) {
      console.error("停止录音与转录失败！", e);
    }
  }, []);

  const onReRecord = useCallback(() => {
    // 清空录音与转录结果
    setRecordingState("recording");
    resetTranscript();
    audioChunksRef.current = [];
    audioBlobRef.current = null;
    // 重新开始录音与转录（使用onStart）
    void onStart();
  }, [onStart, resetTranscript]);

  const onSubmit = useCallback(
    async function () {
      // 提交录音与转录结果
      // -1. 检测transcript
      if (!transcript.trim()) {
        console.error("没有识别到内容");
        return;
      }
      // 0. 更新messages
      const newMessage = {
        role: "user",
        content: transcript,
        analysis: null,
      };
      const userIndex = messages.length;
      const assistantIndex = userIndex + 1;
      setMessages((prev) => {
        // ...后续分析结果合并...
        return [...prev, newMessage, {role: "assistant", content: ""}];
      });
      // 1. 获取对话回复
      let assistantContent = "";
      let assistantId = null;
      const eventSource = updateChat(chatId, transcript, chatInfo.situation);
      eventSource.onmessage = (event) => {
        const data = JSON.parse(event.data);
        if (data.type === "text") {
          assistantContent += data.content || "";
          setMessages((prev) => {
            const updated = [...prev];
            updated[assistantIndex] = {
              ...updated[assistantIndex],
              content: assistantContent,
            };
            return updated;
          });
        } else if (data.type === "audio" && data.content) {
          // 播放 base64 PCM 音频
          if (audioPlayingRef.current) {
            // 如果正在播放，则加入队列
            audioQueueRef.current.push(data.content);
          } else {
            // 如果没有正在播放，则直接播放
            audioPlayingRef.current = true;
            playAudio(data.content);
          }
        } else if (data.index === -1 && data.type === "id") {
          assistantId = data.content;
        }
      };
      eventSource.onerror = (err) => {
        console.error("assistant 回复出错", err);
        eventSource.close();
      };
      // 2. 获取分析
      let grammarResult = null;
      let pronResult = null;
      try {
        grammarResult = await analyzeGrammar(transcript);
        setMessages((prev) => {
          const updated = [...prev];
          const oldAnalysis = updated[userIndex].analysis || {};
          updated[userIndex] = {
            ...updated[userIndex],
            analysis: {...oldAnalysis, grammar: grammarResult},
          };
          return updated;
        });
      } catch {
        grammarResult = "语法分析失败。";
      }

      try {
        pronResult = await analyzePronunciation(
          transcript,
          audioBlobRef.current,
        );
        setMessages((prev) => {
          const updated = [...prev];
          const oldAnalysis = updated[userIndex].analysis || {};
          updated[userIndex] = {
            ...updated[userIndex],
            analysis: {...oldAnalysis, pronunciation: pronResult},
          };
          return updated;
        });
      } catch {
        pronResult = "发音分析失败。";
      }
      // 4. 上传消息与分析
      try {
        await saveAnalysis(
          assistantId,
          grammarResult,
          pronResult?.pronAnalysis || "无",
          pronResult?.pronEvaluation || null,
        );
      } catch (e) {
        console.error("保存分析失败", e);
      }
      // 5. 后续处理
      eventSource.onclose = () => {
        console.log("EventSource closed");
      };
      resetTranscript();
      setRecordingState("idle");
    },
    [chatId, transcript, resetTranscript, setMessages, setRecordingState, playAudio, messages.length],
  );

  // Voice模式
  const [noSpeechCount, setNoSpeechCount] = useState(0); // 语音识别未检测到语音的次数
  const [paused, setPaused] = useState(false); // 是否暂停语音识别
  const [currentVoiceRole, setCurrentVoiceRole] = useState("");
  const [currentVoiceText, setCurrentVoiceText] = useState("");
  const lastTranscriptRef = useRef(transcript);
  const submitTimerRef = useRef(null);
  const isSubmittingRef = useRef(false); // 防止重复提交

  useEffect(() => {
    if (recordingState === "recording") {
      setCurrentVoiceRole("user");
      setCurrentVoiceText(transcript);
    } else if (messages.length > 0) {
      setCurrentVoiceRole(messages[messages.length - 1].role);
      setCurrentVoiceText(messages[messages.length - 1].content);
    }
  }, [recordingState, transcript, messages]);

  useEffect(() => {
    console.log("🔄 [Voice Submit Effect] 触发，当前 transcript:", transcript);
    console.log("条件检查: viewMode =", viewMode, ", recordingState =", recordingState, ", paused =", paused);

    if (viewMode !== "voice" || paused || audioPlayingRef.current) {
      console.log("⚠️ 条件不满足，跳过");
      return;
    }

    // 1️⃣ 开始录音（如果处于 idle 状态）
    if (recordingState === "idle") {
      void onStart();
      console.log("🎙️ 开始录音");
    }

    // 2️⃣ 清除之前的定时器
    if (submitTimerRef.current) {
      clearTimeout(submitTimerRef.current);
      submitTimerRef.current = null;
      console.log("⏰ 定时器已清除");
    }

    // 3️⃣ 如果 transcript 为空，不设置定时器
    if (!transcript.trim()) {
      console.log("💬 transcript 为空，暂不设置定时器");
      lastTranscriptRef.current = transcript;
      return;
    }

    console.log("✅ transcript 非空，设置 2 秒提交定时器");

    // 4️⃣ 设置定时器：2秒无更新则提交
    submitTimerRef.current = setTimeout(async () => {
      if (isSubmittingRef.current) {
        console.log("🚫 已在提交中，避免重复提交");
        return;
      }

      if (lastTranscriptRef.current === transcript) {
        console.log("⏳ transcript 2秒无变化，准备提交...");

        isSubmittingRef.current = true;

        setNoSpeechCount(0); // 重置未检测到语音次数
        await onStop(); // 停止录音
        console.log("🛑 录音已停止");

        setTimeout(() => {
          onSubmit(); // 提交内容
          console.log("📤 内容已提交:", transcript);
        }, 100);

        isSubmittingRef.current = false;
      } else {
        console.log("🔁 transcript 有更新，继续监听...");
      }
    }, 2000);

    // 5️⃣ 更新最后一次 transcript
    lastTranscriptRef.current = transcript;

    // 6️⃣ 清理副作用
    return () => {
      if (submitTimerRef.current) {
        clearTimeout(submitTimerRef.current);
        submitTimerRef.current = null;
        console.log("🧹 定时器已清理");
      }
    };
  }, [
    viewMode,
    recordingState,
    paused,
    onStart,
    onStop,
    onSubmit,
    transcript,
  ]);

  function onPause() {
    // 暂停语音识别
    setPaused(true);
    setNoSpeechCount(0);
    setRecordingState("idle");
  }

  return (
    <Layout className="layoutRoot">
      <AppHeader/>
      <Content className="contentBox">
        <Flex
          vertical={true}
          style={{width: "100%", height: "100%"}}
        >
          <ChatInfoPanel
            chatInfo={chatInfo}
            onClose={onClose}
            onSummarize={onSummarize}
            view={viewMode}
            onSetView={handleSwitch}
          />
          {viewMode === "chat" ? (
            <Flex
              vertical={true}
              justify="center"
              style={{width: "100%", height: "80%"}}
            >
              <ChatView messages={messages}/>
              <MessageInput
                transcriptionResult={transcript}
                recordingState={recordingState}
                onStart={onStart}
                onStop={onStop}
                onReRecord={onReRecord}
                onSubmit={onSubmit}
              />
            </Flex>
          ) : (
            <VoiceView
              role={currentVoiceRole}
              text={currentVoiceText}
              paused={paused}
              onPaused={onPause}
              setPaused={setPaused}
            />
          )}
        </Flex>
      </Content>
    </Layout>
  );
}

export default ChatPage;
